//********************************************************************
//	created:	15:11:2012   22:54
//	filename: 	addresshelper.h
//	author:		tiamo	
//	purpose:	address helper
//********************************************************************

#pragma once

namespace network
{
	//
	// address helper
	//
	class AddressHelper
	{
	public:
		//
		// constructor
		//
		AddressHelper()														{memset(&mAddress, 0, sizeof(mAddress));}

		//
		// to string
		//
		UniString toString(bool includePort = true) const;

		//
		// from string
		//
		bool fromString(UniString const& ip, uint16_t port);

		//
		// get address list
		//
		static std::list<AddressHelper> getAddressList(UniString const& hostName, uint16_t port);

		//
		// attach
		//
		bool attach(sockaddr const* address, uint32_t length, uint16_t port = 0);

		//
		// attach
		//
		void attach(sockaddr_in const& address)								{mAddress.v4 = address;}

		//
		// attach
		//
		void attach(sockaddr_in6 const& address)							{mAddress.v6 = address;}

		//
		// attach
		//
		void attach(in_addr const& ip, uint16_t port)						{memset(&mAddress, 0, sizeof(mAddress)); mAddress.v4.sin_family = AF_INET; mAddress.v4.sin_addr = ip; mAddress.v4.sin_port = htons(port);}

		//
		// attach
		//
		void attach(in6_addr const& ip, uint16_t port)						{memset(&mAddress, 0, sizeof(mAddress)); mAddress.v6.sin6_family = AF_INET6; mAddress.v6.sin6_addr = ip; mAddress.v6.sin6_port = htons(port);}

		//
		// get port
		//
		uint16_t getPort() const											{return mAddress.v6.sin6_family == AF_INET6 ? ntohs(mAddress.v6.sin6_port) : (mAddress.v4.sin_family == AF_INET ? ntohs(mAddress.v4.sin_port) : 0);}

		//
		// get address
		//
		sockaddr const* getAddress() const									{return reinterpret_cast<sockaddr const*>(&mAddress);}

		//
		// get address length
		//
		uint32_t getAddressLength() const									{return mAddress.v6.sin6_family == AF_INET6 ? sizeof(mAddress.v6) : (mAddress.v4.sin_family == AF_INET ? sizeof(mAddress.v4) : 0);}

		//
		// get family
		//
		int getFamily() const												{return mAddress.v4.sin_family;}

		//
		// is valid
		//
		bool isValid() const												{return mAddress.v4.sin_family == AF_INET || mAddress.v6.sin6_family == AF_INET6;}

	private:
		//
		// address
		//
		union {sockaddr_in v4; sockaddr_in6 v6;}							mAddress;
	};
}
